
using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.SessionState;
using System.Web.Routing;
using System.IO;
using SoftwareMonkeys.Scriptech.Web;
using SoftwareMonkeys.Scriptech.Diagnostics;
using SoftwareMonkeys.Scriptech.State;
using SoftwareMonkeys.Scriptech.Configuration;
using SoftwareMonkeys.Scriptech.Web.Data;
using SoftwareMonkeys.Scriptech.Data;
using SoftwareMonkeys.Scriptech.Entities;
using SoftwareMonkeys.Scriptech.Business;
using SoftwareMonkeys.Scriptech.Web.Projections;
using SoftwareMonkeys.Scriptech.Web.Controllers;
using SoftwareMonkeys.Scriptech.Scripts;

namespace WWW
{


	public class Global : System.Web.HttpApplication
	{
		
		public static void RegisterRoutes (RouteCollection routes)
		{
			
			routes.RouteExistingFiles = true;
			routes.Add("Scripts", new Route("Scripts/{script}", new ScriptRouteHandler()));

			routes.Add("Projections", new Route("{verb}-{noun}.aspx", new ProjectionRouteHandler()));

		}
		
		void ResetTmpFolder ()
		{
			try
			{
				string tmpFolder = Server.MapPath ("~/Scripts/tmp");
				
				if (Directory.Exists (tmpFolder))
				{
					foreach (string file in Directory.GetFiles(tmpFolder))
						File.Delete(file);

					Directory.Delete (tmpFolder, true);
				}
			}
			catch (Exception ex)
			{
				LogWriter.Error(ex);
			}
		}

		protected virtual void Application_Start (Object sender, EventArgs e)
		{
			HttpContext.Current.Server.ScriptTimeout = 30 // minutes
				* 60 // seconds
				* 1000; // milliseconds;
			
			InitializeCore();
			
			// Start a log group for the application
			HttpContext.Current.Application["Application_Start.LogGroup"] = LogGroup.StartDebug("Starting application.");
			
			LogWriter.Debug("${Application.Start}");
			
			// Attempt to initialize the config
			Initialize();
			
			ResetTmpFolder ();
			
			RegisterRoutes (RouteTable.Routes);
		}

		protected virtual void Session_Start (Object sender, EventArgs e)
		{
			//InitializeCore();
			
			// Create a log group for the session
			HttpContext.Current.Session["Session_Start.LogGroup"] = LogGroup.StartDebug("Starting session.");
			
			//	Initialize();
			
		}

		protected virtual void Application_BeginRequest (Object sender, EventArgs e)
		{
			// TODO: Check if initialization is needed
			//InitializeCore();
			
			// Create a log group for the request
			HttpContext.Current.Items["Application_BeginRequest.LogGroup"] = LogGroup.StartDebug("Beginning request: " + HttpContext.Current.Request.Url.ToString());

				
					//Initialize();
					
					// TODO: Replace with routing
					//UrlRewriter.Initialize();
			
		}

		protected virtual void Application_EndRequest (Object sender, EventArgs e)
		{
			// Dispose the request log group
			HttpContext.Current.Items["Application_BeginRequest.LogGroup"] = null;

		}

		protected virtual void Application_AuthenticateRequest (Object sender, EventArgs e)
		{
		}

		protected virtual void Application_Error (Object sender, EventArgs e)
		{
			HandleError();
		}

		protected virtual void Session_End (Object sender, EventArgs e)
		{
			// Dispose the session log group
			HttpContext.Current.Session["Session_Start.LogGroup"] = null;
		}

		protected virtual void Application_End (Object sender, EventArgs e)
		{
			// Dispose the application log group
			HttpContext.Current.Application["Application_Start.LogGroup"] = null;

			// Dispose outside the logging as the diagnostics get disposed too
			Dispose();
		}
		

		private void InitializeCore()
		{
			//if (!StateAccess.IsInitialized)
			//{
				InitializeState();
			//}
		}
		
		private void Initialize()
		{
			InitializeConfiguration();
			
			InitializeEntities();
			
			InitializeData();
			
			InitializeBusiness();
			
			
			InitializeWeb();
		}
		
		private void InitializeState()
		{
			SoftwareMonkeys.Scriptech.Web.State.StateProviderInitializer.Initialize();
		}
		
		private void InitializeConfiguration()
		{
			Config.Initialize(Server.MapPath(HttpContext.Current.Request.ApplicationPath), WebUtilities.GetLocationVariation(HttpContext.Current.Request.Url));
		}
		
		private void InitializeEntities()
		{
			new EntityInitializer().Initialize();
		}
		
		private void InitializeData()
		{
			new DataProviderInitializer().Initialize();
		}
		
		private void InitializeBusiness()
		{
			new StrategyInitializer().Initialize();
			new ReactionInitializer().Initialize();
		}
		
		private void InitializeWeb()
		{
			//PartsInitializer.DefaultScanners = new PartScanner[] {
    		//		new PartScanner(),
    		//		new ModulePartScanner()
    		//		};
    				
    		ProjectionsInitializer.DefaultScanners = new ProjectionScanner[] {
    				new ProjectionScanner()
    				};
 
 			//new PartsInitializer().Initialize();
 			new ProjectionsInitializer().Initialize();
 			new ControllersInitializer().Initialize();
		}
		

		public override void Dispose()
		{
			LogWriter.Debug("Disposing application components.");
			
			Config.Dispose();
			// SoftwareMonkeys.Scriptech.Modules.ModuleState.Dispose();
			DataAccess.Dispose(true);

			base.Dispose();
		}
		
		public void HandleError()
		{
			using (LogGroup logGroup = LogGroup.StartDebug("Application error."))
			{
				LogWriter.Debug("${Application.Error}");
				
				Exception lastException = Server.GetLastError();
				
				ExceptionHandler handler = new ExceptionHandler();
				handler.Handle(lastException);
			}
		}
	}
}

